home *** CD-ROM | disk | FTP | other *** search
/ Cracking 2 / Cracking II..iso / Texty / crackme / RTQSOLN.TXT < prev    next >
Encoding:
Text File  |  1998-06-14  |  8.4 KB  |  238 lines

  1. A solution to RTQ's crackme
  2. ---------------------------
  3.  
  4. Written by Prophecy (prophecy_@usa.net)
  5. 13th June 1998
  6.  
  7. (Basic knowledge of Softice is assumed)
  8.  
  9. Part 1:  Tools required
  10. -----------------------
  11.  
  12. All you need is Softice :)
  13.  
  14. Part 2:  Breaking into the target and locating the main code checking routine
  15. -----------------------------------------------------------------------------
  16.  
  17. Well this is the first DOS proggie I've ever looked at, so I took a little time
  18. here.  Basically what I did was:
  19.  
  20. (1) set bpx bpint 21 if ah==9
  21. (2) typed in a bogus code
  22. (3) softice broke when i hit 'enter' (by this time it's already too late, the
  23. code has already been checked)
  24. (4) i searched for my code in memory and by chance it found it in 0:e8b
  25. (5) i then put a bpr on 0:e8b
  26. (6) i then entered a new code, each char i pressed, softice broke, i hit <F5>
  27. to go back to the crackme and enter a new char.
  28. (7) when i finished my entering my code by pressing enter, softice broke here:
  29.  
  30. FF03:5463  AA                  STOSB
  31. FF03:5464  E84602              CALL    56AD
  32. .
  33. .
  34. FF03:5476  F3A4                REPZ MOVSB
  35. FF03:5478  C3                  RET
  36.  
  37. (8) tracing the code, i soon reached what we were looking for: the place where
  38. the crackme checks to see if the code is valid!!!
  39.  
  40. Part 3:  How the target manipulates the code entered by the user
  41. ----------------------------------------------------------------
  42.  
  43. Basically, the crackme consists of a few simple checks to see if the code is
  44. valid.
  45.  
  46. 0EE4:07B0  MOV     SI,DX
  47. 0EE4:07B2  MOV     AL,[SI] ;put length of code into AL
  48. 0EE4:07B4  SBB     AL,0B ;subtract from 0xb
  49. 0EE4:07B6  JNZ     0859 ;jump bad_guy if not zero (Condition 0)
  50.  
  51. Pretty simple, code has to be 0xb (11) chars long, which you'll note fits
  52. perfectly inside the [           ] ... so no surprises here.  Either go back
  53. and enter a new 11 char code or reverse the jump (r fl z).
  54.  
  55. 0EE4:07BA  MOV     SI,DX
  56. 0EE4:07BC  XOR     BX,BX ;set bx=0
  57. 0EE4:07BE  MOV     CX,0005 ;do 5 loops
  58. 0EE4:07C1  LODSW ;load word at ds:si (which is your code)
  59. 0EE4:07C2  ADD     AL,AH ;add high byte to low byte
  60. 0EE4:07C4  XOR     AH,AH ;set ah=0
  61. 0EE4:07C6  ADD     BX,AX ;add ax to bx
  62. 0EE4:07C8  LOOP    07C1 ;go back to 07c1
  63. 0EE4:07CA  XOR     AX,AX ;set ax=0
  64. 0EE4:07CC  LODSB ;load byte at cs:dx
  65. 0EE4:07CD  ADD     BX,AX ;add 10th char of code to checksum
  66. 0EE4:07CF  CMP     BX,042D ;compare total with 0x42d
  67. 0EE4:07D3  JNZ     0859 ;jump bad_guy if not zero (Condition 1)
  68.  
  69. Ok, this is pretty simple too...
  70.  
  71. cs:dx is your code with the length of the code in front, ie if you entered
  72. 12345678901 as your code, then cs:dx is this:
  73.  
  74. 0b 31 32 33 34 35 36 37 38 39 30 31 <- code and length
  75. 0  1  2  3  4  5  6  7  8  9  10 11 <- char number i use as reference
  76.  
  77. So the above code segment takes the first word 310b, adds 0b to 31 giving
  78. 3c which is stored in al.  it then adds ax to bx which is initally zero.
  79. it then takes the 2nd word 3332 and adds the 32 to 33, giving 65.  It then
  80. adds that 65 to bx, which is 3c, giving a1 etc... it does this with chars
  81. 0 thru to 9.  It finally adds the 10th value to the sum and compares it
  82. with 0x42d.  So basically all this is doing is:
  83.  
  84. char 0 + char 1 + char 2...+char 10 = 0x42d, so 0x42d is just a checksum.
  85.  
  86. i now typed r bx and entered 42d and continued tracing.
  87.  
  88. 0EE4:07D7  INC     DX
  89. 0EE4:07D8  ADD     CX,02
  90. 0EE4:07DB  MOV     SI,DX
  91. 0EE4:07DD  MOV     DI,AX ;moves ax which is char 10 into di
  92. 0EE4:07DF  REPZ MOVSB
  93. 0EE4:07E1  MOV     DI,AX
  94. 0EE4:07E3  MOV     AX,[DI] ;moves what di points to into ax
  95. 0EE4:07E5  XOR     AH,AL
  96. 0EE4:07E7  OR      AL,AH
  97. 0EE4:07E9  NEG     AX
  98. 0EE4:07EB  SUB     AX,FFE0
  99. 0EE4:07EE  JNZ     0859 ;if ax not equal to ffe0, jump bad_guy (Condition 2)
  100.  
  101. So, basically it takes the 10th char and puts into di, then it retrieves
  102. what di is now pointing to and sticks in ax.  So lets say ax is now equal
  103. to XY , where X,Y are the two bytes of ax.  So X get xored with Y, result Z
  104. is stored in ah, giving ZY as the new value of ax.  Then al is ored with ah,
  105. result Q is stored in al giving ZQ as new value of ax.  Then ax is negated
  106. and compared with FFE0.  So we want XY to be a number that after the above
  107. steps equals FFE0... you dig?  What is that number you say?  Well i just
  108. decided to negate E0 (? -e0 in softice) and i got 20... So i looked in the
  109. general area of di which was 0x30 at the time (10th char of my code) and
  110. noticed further down a whole buch of 20 20 20 20 20... it became evident
  111. the necessary XY values were 20 and 20.
  112.  
  113. There were 2 rows of 20: one starting at 0x5d going to 0x66 and
  114.                          one starting at 0x6d gonig to 0x76
  115.  
  116. So the 10th char must be in that range!
  117.  
  118. At this stage i typed r ax and entered ffe0 and then continued on:
  119.  
  120. 0EE4:07F0  NOP
  121. 0EE4:07F1  NOP
  122. 0EE4:07F2  ADD     CX,02 ;set counter=2
  123. 0EE4:07F5  MOV     DI,AX ;ax=0000 from above... as you can see it was a good
  124. idea to change the value of the register as opposed to just reversing the
  125. jump or else it would have stuffed up here.
  126. 0EE4:07F7  LODSW
  127. 0EE4:07F8  OR      AL,AH
  128. 0EE4:07FA  SUB     AL,AH
  129. 0EE4:07FC  STOSB
  130. 0EE4:07FD  LOOP    07F7
  131. 0EE4:07FF  MOV     CX,0002
  132. 0EE4:0802  PUSH    DX
  133. 0EE4:0803  SUB     DI,02 ;set di back to zero because of the loop
  134. 0EE4:0806  MOV     AX,[DI] ;move contents of di into ax
  135. 0EE4:0808  DEC     AX ;decrease ax by 1
  136. 0EE4:0809  OR      BX,AX ;or the checksum (42d) with ax
  137. 0EE4:080B  OR      AX,BX ;or ax with the checksum
  138. 0EE4:080D  SUB     AX,24ED ;ax=ax-24ed
  139. 0EE4:0810  POP     DX
  140. 0EE4:0811  JNZ     0859 ;jump bad guy if ax not equal to 24ed (Condition 3)
  141.  
  142. This is pretty self explanatory.  If you had changed the contents of the
  143. registers to what they were suppose to be instead of simply just reversing
  144. the jump, then ax would equal 24ed at the end.. no extra work required!
  145.  
  146. 0EE4:0813  NOP
  147. 0EE4:0814  NOP
  148. 0EE4:0815  MOV     SI,DX
  149. 0EE4:0817  LODSW
  150. 0EE4:0818  MOV     BX,AX
  151. 0EE4:081A  LODSW
  152. 0EE4:081B  LOOP    0817
  153. 0EE4:081D  SUB     AX,BX
  154. 0EE4:081F  SUB     AX,01F8
  155. 0EE4:0822  JNZ     0859 ;jump bad_guy if ax not equal to zero (Condition 4)
  156.  
  157. This is a simple check which does this:
  158.  
  159. if ax-bx-0x1f8 not equal to zero, jump bad_guy... ax=RS, and bx=TU, where:
  160. R=char 8, S=char 7, T=char 6, U=char 5. So this is pretty braindead stuff,
  161. just make sure the above condition holds to bypass the protection section.
  162.  
  163. i type r ax and entered 01f8 and continued tracing.
  164.  
  165. 0EE4:0824  NOP
  166. 0EE4:0825  NOP
  167. 0EE4:0826  SUB     SI,02
  168. 0EE4:0829  LODSW
  169. 0EE4:082A  ADD     AH,AL
  170. 0EE4:082C  ADD     AH,AH
  171. 0EE4:082E  MOV     BH,AH
  172. 0EE4:0830  LODSB
  173. 0EE4:0831  SUB     AH,BH
  174. 0EE4:0833  JNZ     0859 ;jump if ah-bh not equal to zero (Condition 5)
  175. 0EE4:0835  NOP
  176. 0EE4:0836  NOP
  177. 0EE4:0837  CALL    0755
  178.  
  179. This check is kinda pointless as it will never jump.  Probably designed
  180. to fool crackers who have reversed all the previous jumps successfully and
  181. on reversing the last jump, it will stuff up!!  So just step over that
  182. last JNZ and bang, RTQ's crackme says "WELL DONE".
  183.  
  184. Part 4:  Calculating a valid code
  185. ---------------------------------
  186.  
  187. Well there are many codes that will work for this crackme.  I only calculate
  188. a possible code.
  189.  
  190. (1) satisfied condition 4:
  191.  
  192. if ax-bx-0x1f8 not equal to zero, jump bad_guy... ax=RS, and bx=TU, where:
  193. R=char 8, S=char 7, T=char 6, U=char 5.
  194.  
  195. i set ax=6941 and bx=6749.  Hence, chars 5-8 of my code are: IgAi
  196.  
  197. and 0x6941-0x6749=1f8, hence, condition satisfied.
  198.  
  199. (2) satisfy condtion 0, 1, 2, 3 and 5
  200.  
  201. well, we know the sum of the first 10 chars + length of code must equal 0x42d.
  202. also the 10th char must be >= 5d and <=66 or >=6d and <=76.  and the code must
  203. be 11 chars long.
  204.  
  205. So, it was just a simple matter of trial and error before i got a valid code:
  206.  
  207. vvvvIgAizv!
  208.  
  209. The hex ascii values of the letters are: v=76, I=49, g=67, A=41, i=69 and z=7a.
  210. The length of the code is 0xb. (condition 0 satisfied)
  211.  
  212. So, 4(76)+49+67+41+69+7a+76=42d (condtion 1 satisfied)
  213.  
  214. Then, the 10th char of the code is 0x76 which is within the valid range
  215. specified above. (condition 2 satisfied).
  216.  
  217. The '!' can be any char, it's just a place holder to make sure the code is 11
  218. chars long.
  219.  
  220. And that's it... simple eh?
  221.  
  222. Part 5:  Greetz
  223. ---------------
  224.  
  225. Greetz fly out to the #cracking4newbies crew on efnet.
  226.  
  227. Part 6:  Conclusion
  228. -------------------
  229.  
  230. I hope you enjoyed the tut.  You can send me email to prophecy_@usa.net if you
  231. have any problems etc... -Prophecy (13th June 1998)
  232.  
  233. Veni Vedi Vici.
  234.  
  235.  
  236. ------ end of soln ------
  237.  
  238.